package com.sxbbc.common.basics.service.redis;

import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import common.Logger;


@Service
public class RedisUtilsService {

    protected final static Logger logger = Logger.getLogger(RedisUtilsService.class);
    @Autowired
    private volatile RedisTemplate<String, String> redisTemplate;

    /**
     * 秒级内做并发处理
     *
     * @param key
     * @param cacheSeconds
     * @return true 表示可以继续下面逻辑没有并发  false表示并发数据
     */
    public boolean setIncrSecond(String key, long cacheSeconds) {
        try {
            setStringSerializer(redisTemplate);
            long count = redisTemplate.opsForValue().increment(key, 1);
            //此段代码出现异常则会出现死锁问题，key一直都存在
            if (count == 1) {
                //设置有效期X秒
                redisTemplate.expire(key, cacheSeconds, TimeUnit.SECONDS);
                return true;
            }
            //如果存在表示重复
            return false;
        } catch (Exception e) {
            logger.error("redis加锁异常", e);
            //出现异常删除锁
            redisTemplate.delete(key);
            return true;
        }
    }

    /**
     * 获取唯一Id
     *
     * @param key
     * @param hashKey
     * @param delta   增加量（不传采用1）
     * @return
     */
    public Long incrementHash(String key, String hashKey, Long delta) {
        try {
            if (null == delta) {
                delta = 1L;
            }
            setStringSerializer(redisTemplate);
            return redisTemplate.opsForHash().increment(key, hashKey, delta);
        } catch (Exception e) {
            //redis宕机时采用uuid的方式生成唯一id
            int first = new Random(10).nextInt(8) + 1;
            int randNo = UUID.randomUUID().toString().hashCode();
            if (randNo < 0) {
                randNo = -randNo;
            }
            return Long.valueOf(first + String.format("%16d", randNo));
        }
    }

    /**
     * 设置无限期 键值对信息
     *
     * @param key
     * @param value
     */
    public void setKey(String key, String value) {
        setStringSerializer(redisTemplate);
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 设置有限期 键值对信息
     *
     * @param key
     * @param value
     * @param second 秒
     */
    public void setKey(String key, String value, long second) {
        setStringSerializer(redisTemplate);
        redisTemplate.opsForValue().set(key, value, second, TimeUnit.SECONDS);
    }


    /**
     * 根据键获取值
     *
     * @param key
     * @return
     */
    public String getKey(String key) {
        String val = redisTemplate.opsForValue().get(key);
        return val;
    }

    /**
     * 删除key
     *
     * @param key
     */
    public void deleteKey(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 根据cid设置set集合
     *
     * @param cid      用户id
     * @param secondId 二级分类ID
     * @author leehao
     */
    public void setSecondKey(String cid, String secondId) {
        setStringSerializer(redisTemplate);
        redisTemplate.opsForSet().add(cid, secondId);
    }

    /**
     * 根据cid获取set集合
     *
     * @param cid 用户ID
     * @return 二级分类的set集合
     * @author leehao
     */
    public Set<String> getSecondValue(String cid) {
        setStringSerializer(redisTemplate);
        Set<String> set = redisTemplate.opsForSet().members(cid);
        return set;
    }

    /**
     * 序列化redis key 避免乱码
     *
     * @param template
     */
    private void setStringSerializer(RedisTemplate<String, String> template) {
        RedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setDefaultSerializer(stringRedisSerializer);
        template.setKeySerializer(stringRedisSerializer);
        template.setValueSerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setHashValueSerializer(stringRedisSerializer);
    }

    /**
     * 查询key的生命周期
     *
     * @param key
     * @param timeUnit
     * @return
     * @author Wahyee
     */
    public long getExpire(String key, TimeUnit timeUnit) {
        return redisTemplate.getExpire(key, timeUnit);
    }
}
